package edu.umb.cs.antmanager.client;

import static edu.umb.cs.antmanager.common.Constants.*;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;

import edu.umb.cs.antmanager.common.AgentControlIntFace;

/**
 * Used to dispatch an agent. Once started, the dispatcher will never die,
 * unless you kill it explicitly. The dispatcher runs on it's own Registry in a
 * separate process;
 * 
 * @author 2009CS682-3UMB_AntManager
 * 
 */
public class AgentDispatcher extends UnicastRemoteObject implements
		AgentControlIntFace {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	protected AgentDispatcher() throws RemoteException {
		super(CONTROL_PORT);
		System.setProperty("java.security.policy", SECURITY_FILE);
		// Required by RMI, used to find the server's java class
		System.setProperty("java.rmi.server.codebase", CODE_BASE);
		// if there is not security manager, create one.
		if (System.getSecurityManager() == null) {
			System.setSecurityManager(new SecurityManager());
		}
		try {
			// Try to create a new registry.
			LocateRegistry.createRegistry(CONTROL_PORT);
		} catch (RemoteException e) {
			// There is a running Registry on that port, don't need
			// to create another one, just need to bind the agent
		}
		Registry registry = LocateRegistry.getRegistry(CONTROL_PORT);
		try {
			registry.bind(AGENT_CONTROLLER, this);
		} catch (AlreadyBoundException e) {
			// only one dispatcher is allow in one system.
			System.exit(0);
		}
	}

	@Override
	public void start() throws RemoteException {
		try {
			Remote r = Naming.lookup("rmi://localhost:" + AGENT_PORT + "/"
					+ AGENT_SERVER_NAME);
			if (r != null)
				return;
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
		} catch (RemoteException e) {
		}
		String javaHome = System.getenv("JAVA_HOME");
		String cp = System.getProperty("java.class.path");
		ArrayList<String> argList = new ArrayList<String>();
		if (javaHome != null)
			argList.add(javaHome + "/bin/java");
		else
			argList.add("java");
		argList.add("-classpath");
		argList.add(cp);
		argList.add(RMIAgentServer.class.getName());
		ProcessBuilder pb = new ProcessBuilder(argList);
		pb.directory(new File(ANT_MANAGER_HOME));
		try {
			pb.start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Start the dispatcher.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			System.setProperty("java.rmi.server.hostname", java.net.InetAddress
					.getLocalHost().getHostName());
		} catch (UnknownHostException e) {
		}
		try {
			new AgentDispatcher();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

}
